package com.zg.nacos.web;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.zg.common.core.R;
import com.zg.common.core.util.IpUtils;
import com.zg.nacos.domain.req.*;
import com.zg.nacos.util.NacosUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.nio.file.AccessDeniedException;
import java.time.Duration;
import java.util.List;
import java.util.Map;

/**
 * <p>Description: </p>
 *
 * @author zhanfeng.liang
 * @since 2025/6/20 16:11
 */

@RestController
@RequestMapping("/nacos")
@Api(tags = "nacos服务")
@Slf4j
public class NacosConfigController {

    @Autowired
    private WebClient webClient;


    /**
     * 配置列表
     *
     * @param configPageReq
     * @return
     */
    @ApiOperation(value = "配置列表")
    @PostMapping("/config/page")
    public R pageConfig(@Valid @RequestBody ConfigPageReq configPageReq) {
        return webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/nacos/v1/cs/configs")
                        .queryParam("dataId", "*"+configPageReq.getDataId()+"*")
                        .queryParam("group", configPageReq.getGroup())
                        .queryParam("tenant", configPageReq.getTenant())
                        .queryParam("pageSize", configPageReq.getPageSize())
                        .queryParam("pageNo", configPageReq.getPageNo())
                        //.queryParam("search", "accurate")
                        .queryParam("search", "blur")
                        .queryParam("accessToken", configPageReq.getNacosToken())
                        .build())
                .retrieve()
                .bodyToMono(Map.class)
                .map(map -> NacosUtils.genPage(map, configPageReq.getPageNo(), configPageReq.getPageSize()))
                .block(Duration.ofSeconds(5)); // 在最后阻塞获取结果
    }

    /**
     * 配置详情
     * @param configPageReq
     * @return
     */
    /**
     * 配置详情
     *
     * @param configPageReq
     * @return
     */
    @ApiOperation(value = "配置详情")
    @PostMapping("/config/info")
    public R infoConfig(@Valid @RequestBody ConfigInfoReq configPageReq) {
        Map map =getConfig(configPageReq);
        return R.success(map);
    }

    @ApiOperation(value = "配置新增、编辑")
    @PostMapping("/config/edit")
    public Mono<R> editConfig(HttpServletRequest request, @Valid @RequestBody ConfigEditReq configEditReq) {

            // 创建MultiValueMap并指定泛型类型
            MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();

            // 使用add方法添加表单字段（更适合multipart/form-data）
            formData.add("dataId", configEditReq.getDataId());
            formData.add("group", configEditReq.getGroup());
            formData.add("content", configEditReq.getContent());
            if(StrUtil.isNotBlank(configEditReq.getAppName())){
                formData.add("appName", configEditReq.getAppName());
            }

            formData.add("desc", configEditReq.getDesc());
            formData.add("type", configEditReq.getType());
//            formData.add("id", configEditReq.getId());
//            formData.add("md5", MD5.create().digestHex16(configEditReq.getContent()));
            formData.add("tenant", configEditReq.getNamespaceId());
            formData.add("namespaceId", configEditReq.getNamespaceId());

//            // 将Long类型的时间戳转换为字符串
//            formData.add("createTime", String.valueOf(DateUtil.currentSeconds()));
//            formData.add("modifyTime", String.valueOf(DateUtil.currentSeconds()));
//
//            formData.add("createUser", configEditReq.getCreateUser());
//            formData.add("createIp", IpUtils.getClientIpAddress(request));

            return  webClient.post()
                    .uri(uriBuilder -> uriBuilder.path("/nacos/v1/cs/configs")
                            .queryParam("accessToken", configEditReq.getNacosToken())
                            .build())
 //                    .header("username", userName)
//                    .header("password", password)
                    .contentType(MediaType.MULTIPART_FORM_DATA)
                    .body(BodyInserters.fromMultipartData(formData))
                    .retrieve()
                    .bodyToMono(String.class)
                    .map(NacosUtils::handleResponse);

    }

    @ApiOperation(value = "配置新增、编辑")
    @PostMapping("/config/editContent")
    public Mono<R> editConfigContent(HttpServletRequest request, @Valid @RequestBody ConfigContentEditReq configEditReq) {

        // 创建MultiValueMap并指定泛型类型
        MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();

        // 使用add方法添加表单字段（更适合multipart/form-data）
        formData.add("dataId", configEditReq.getDataId());
        formData.add("group", configEditReq.getGroup());
        formData.add("content", configEditReq.getContent());
        formData.add("tenant", configEditReq.getNamespaceId());
        formData.add("namespaceId", configEditReq.getNamespaceId());

        return  webClient.post()
                .uri(uriBuilder -> uriBuilder.path("/nacos/v1/cs/configs")
                        .queryParam("accessToken", configEditReq.getNacosToken())
                        .build())
                //                    .header("username", userName)
//                    .header("password", password)
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .body(BodyInserters.fromMultipartData(formData))
                .retrieve()
                .bodyToMono(String.class)
                .map(NacosUtils::handleResponse);

    }
    @ApiOperation(value = "配置删除")
    @PostMapping("/config/remove")
    public R removeConfig(@Valid @RequestBody ConfigRemoveReq configDeleteReq) {
        // 创建MultiValueMap并指定泛型类型

            MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
            queryParams.add("dataId", configDeleteReq.getDataId());
            queryParams.add("group", configDeleteReq.getGroup());
            queryParams.add("tenant", configDeleteReq.getTenant());
            return webClient.delete()
                    .uri(uriBuilder -> uriBuilder
                            .path("/nacos/v1/cs/configs")
                            .queryParams(queryParams)
                            .queryParam("accessToken", configDeleteReq.getNacosToken())
                            .build())
//                    .header("username", userName)
//                    .header("password", password)
                    .retrieve()
                    .bodyToMono(String.class)
                    .map(NacosUtils::handleResponse)
                    .block(Duration.ofSeconds(5));

    }

    /**
     * 配置历史列表
     *
     * @param historyPageReq
     * @return
     */
    @ApiOperation(value = "配置配置历史列表")
    @PostMapping("/history/page")
    public R pageHistory(@Valid @RequestBody HistoryPageReq historyPageReq) {
        // 创建MultiValueMap并指定泛型类型
        if(StrUtil.isEmpty(historyPageReq.getDataId())||StrUtil.isEmpty(historyPageReq.getGroup())){
            return R.success(new Page<>(historyPageReq.getPageNo(), historyPageReq.getPageSize(), 0));
        }
        MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
        queryParams.add("dataId", historyPageReq.getDataId());
        queryParams.add("group", historyPageReq.getGroup());
        queryParams.add("tenant", historyPageReq.getTenant());
        queryParams.add("search", "accurate");
        return webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/nacos/v1/cs/history")
                        .queryParams(queryParams)
                        .queryParam("accessToken", historyPageReq.getNacosToken())
                        .build())
                .retrieve()
                .bodyToMono(Map.class)
                .map(map -> NacosUtils.genPage(map, historyPageReq.getPageNo(), historyPageReq.getPageSize()))
                .block(Duration.ofSeconds(5)); // 在最后阻塞获取结果;
    }

    /**
     * 配置历史详情
     *
     * @param historyInfoReq
     * @return
     */
    @ApiOperation(value = "配置详情")
    @PostMapping("/history/info")
    public R infoHistory(@Valid @RequestBody HistoryInfoReq historyInfoReq) {
        // 创建MultiValueMap并指定泛型类型

        MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
        queryParams.add("dataId", historyInfoReq.getDataId());
        queryParams.add("group", historyInfoReq.getGroup());
        queryParams.add("tenant", historyInfoReq.getTenant());
        queryParams.add("nid", historyInfoReq.getNid());
        queryParams.add("accessToken", historyInfoReq.getNacosToken());
        return webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/nacos/v1/cs/history")
                        .queryParams(queryParams)
                        .build())
//                .header("username", userName)
//                .header("password", password)
                .retrieve()
                .bodyToMono(Map.class)
                .map(R::success
                ).block(Duration.ofSeconds(5));
    }

    @ApiOperation(value = "最新的配置")
    @PostMapping("/history/diff")
    public R infoDiff(@Valid @RequestBody HistoryInfoReq historyInfoReq) {
        Map historyMap =  getHistory(historyInfoReq);
        ConfigInfoReq configInfoReq = new ConfigInfoReq();
        BeanUtils.copyProperties(historyInfoReq,configInfoReq);
        Map configMap = getConfig(configInfoReq);

        Map map = Maps.newHashMap();
        map.put("history",historyMap.get("content"));
        map.put("config",configMap.get("content"));
        return R.success(map);
    }

    private  Map  getHistory(HistoryInfoReq historyInfoReq) {
        MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
        queryParams.add("dataId", historyInfoReq.getDataId());
        queryParams.add("group", historyInfoReq.getGroup());
        queryParams.add("tenant", historyInfoReq.getTenant());
        queryParams.add("nid", historyInfoReq.getNid());
        queryParams.add("accessToken", historyInfoReq.getNacosToken());
        return  webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/nacos/v1/cs/history")
                        .queryParams(queryParams)
                        .build())
                .retrieve()
                .bodyToMono(Map.class)
                .block(Duration.ofSeconds(5));
    }

    private  Map  getConfig(ConfigInfoReq historyInfoReq) {
        return webClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/nacos/v1/cs/configs")
                        .queryParam("dataId", historyInfoReq.getDataId())
                        .queryParam("group", historyInfoReq.getGroup())
                        .queryParam("tenant", historyInfoReq.getTenant())
                        .queryParam("show", "all")
                        .queryParam("accessToken", historyInfoReq.getNacosToken())
                        .build())
                .retrieve()
                .bodyToMono(Map.class)
                .block(Duration.ofSeconds(5));
    }
}